defmodule FormatView do
    @moduledoc false

    import ProjectType


    def get_views(nil, _, _, _) do
        []
    end
    def get_views(rows, _, [], _) do
        rows
    end
    def get_views(rows, object, views, proj_info) when is_list(rows) do
        {proj_type, project_id, mod_view} = proj_info
        fetch_rows_view_key(rows, mod_view, object, views)
        |> mod_view.get_view_value({proj_type, project_id})
        |> set_rows_view(mod_view, object, rows)
    end
    def get_views(row, object, views, proj_info) do
        get_views([row], object, views, proj_info)
    end

    def fetch_rows_view_key([], _mod, _, _) do
        %{}
    end
    def fetch_rows_view_key(nil, _mod, _, _) do
        %{}
    end
    def fetch_rows_view_key(rows, mod, object, view_keys) do
        Enum.reduce(view_keys, %{}, &fetch_view_key(mod, &2, rows, object, &1))
    end

    defp fetch_view_key(mod, all_acc, rows, object, view_key) do
        Enum.reduce(
            rows,
            all_acc,
            fn
                (nil, acc) ->
                    acc
                (row, acc) ->
                    mod.fetch_view_key(view_key, object, row)
                    |> Enum.reduce(
                           acc,
                           fn
                               nil, acc ->
                                   acc
                               {_, []}, acc ->
                                   acc
                               {_, [nil]}, acc ->
                                   acc
                               {_, nil}, acc ->
                                   acc
                               {key, value}, acc when is_map(value) ->
                                   cur = Map.get(acc, key, %{})
                                   value = Enum.reduce(
                                       value,
                                       cur,
                                       fn ({sub_key, sub_value}, acc2) ->
                                           cur = Map.get(acc2, sub_key, [])
                                           cur = ListKit.append(sub_value, cur)
                                           Map.put(acc2, sub_key, cur)
                                       end
                                   )
                                   Map.put(acc, key, value)
                               {key, value}, acc ->
                                   cur_uids = Map.get(acc, key, [])
                                   value = ListKit.append(value, cur_uids)
                                   Map.put(acc, key, value)
                           end
                       )
            end
        )
    end


    def set_rows_view(_, _mod, _, []) do
        []
    end
    def set_rows_view(_, _mod, _, nil) do
        []
    end
    def set_rows_view(map_value, mod, object, rows) do
        Enum.map(
            rows,
            fn (row) ->
                Enum.reduce(map_value, row, &(mod.set_view_value(&1, object, &2)))
            end
        )
    end

    def get_user_views(proj_type, view_key, user_uids, acc) do
        params = {DoUserImpl, :get_views, %{"uids" => Enum.uniq(user_uids), "proj_type" => proj_type}}
        with {:ok, json_values} <- SwarmUtil.sync_call(AppConfigure.fetch(:user_auth), params) do
            Map.put(acc, view_key, json_values)
        else
            _ ->
                Map.put(acc, view_key, %{})
        end
    end

end
